--[[
 -- *名称:ddztypeutil
 -- *描述:工具类
 -- *版权:Copyright © 2016-2018 深圳市三只小熊科技有限公司 版权所有
 -- *作者:Administrator
 -- *创建日期:2017-11-08
 -- *修改日期:2017-11-08
 -- @return [description]
 ]]

local M = {} ;
local Cards = require(basePath .. "domain/cards")
--[[
 -- [ensureStaight 是否可以找到相应顺几张的顺子]
 期间可以用癞子去做填补，癞子不够也不行
 -- @DateTime 2017-11-08
 -- @param    beginValue 开始值
 -- @param    tupleSize 元组牌数量
 -- @param    straightNeed 顺几张
 -- @param    cards [description]
 -- @param    term [description]
 -- @param    result [description]
 -- @return    [description]
 ]]
M.ensureStaight = function(beginValue,tupleSize,straightNeed,cards,term,result)
	local laiziCardNum = result:getLaziCardNum();
	local allNeedLaiziCardNum = 0 ;
	--分析有几组牌
	local tupleNum = result:getCardNum() / tupleSize ;
	local valueTemp = beginValue ;
	while valueTemp > (beginValue - tupleNum) do
		if (valueTemp < PokerGameConstant.NUMBER_3_VALUE) then -- // 不能继续顺下去
				return false;
		end
		local valueTempNum = result:getNoneLaziValueCounter():getValueCount(valueTemp);
		local needLaziNum = straightNeed - valueTempNum ;
		needLaziNum = needLaziNum > 0 and needLaziNum or 0 ;
		allNeedLaiziCardNum = allNeedLaiziCardNum + needLaziNum;
		if laiziCardNum < allNeedLaiziCardNum then
			return false ;
		end
		valueTemp = valueTemp - 1 ;
	end
	return true ;
end

M.getNumberByValue = function(value) 
	if (value == PokerGameConstant.RED_JOKER_SHAPE_VALUE)  then
		return PokerGameConstant.RED_JOKER_SHAPE_NUM;
    elseif (value == PokerGameConstant.BLACK_JOKER_SHAPE_VALUE) then
		return PokerGameConstant.BLACK_JOKER_SHAPE_NUM;
	elseif (value == PokerGameConstant.NUMBER_2_VALUE) then
		return 2;
	elseif (value == PokerGameConstant.NUMBER_1_VALUE) then
		return 1;
	else -- 1 - 13
		return value;
	end

end

--[[
 -- 从指定牌列中获取部分牌，从原牌列中移除
 -- @DateTime 2017-11-09
 -- @param    cards [description]
 -- @param    value 指定牌value值
 -- @param    need 数量
 -- @return    [description]
 ]]
-- M.obtainsPartCards = function(cards,value,need)
-- 	local cardsResult = {} ;
-- 	local cardList = cards:getCardList() ;
-- 	for i= #cardList,1,-1 do
-- 		local card = cardList[i] ;
-- 		if card:getValue() == value then
-- 		   table.insert(cardsResult,card) ;
-- 		   table.remove(cardList,i);
-- 		   need = need - 1 ;
-- 		   if need == 0 then
-- 		   		break ;
-- 		   end
-- 		end
-- 	end
-- 	return cardsResult ;

-- end

---
 -- [createCloneCards 创建Cards对象，引用的牌为深克隆]
 -- @DateTime 2017-11-09
 -- @param    cardList [description]
 -- @return    [description]
 --
-- M.createCloneCards = function(cardList)
--   return pokercore.new(Cards,pokercore.clone(cardList)) ;
-- end

-- M.createCloneCards2 = function(cards,cardList)
--   local cardsTemp = cards:clone();
--   cardsTemp:addCards(pokercore.clone(cardList)) ;
--   return cardsTemp ;
-- end
-- ---
 -- [revert2Cards 回复排列，会还原癞子，对应方法obtainsSubCards ]
 -- @DateTime 2017-11-09
 -- @param    cards [description]
 -- @param    cardList [description]
 -- @return    [description]
 --
-- M.revert2Cards = function(cards,cardList)
-- 	for _,card in ipairs(cardList) do
-- 		card:changeCard(0) ;
-- 	end
-- 	cards:addCards(cardList);
--     PokerUtil.sortCards_asc(cards);
-- end

---
 -- 提对子牌算法，从手牌中分析出单张牌出来 <br>
 -- 比如手牌 21QJ986554443 可以出的对子牌就有 55 44 考虑拆牌
 -- @DateTime 2017-11-09
 -- @return   [description]
 --
-- M.selectPairCards = function(cards)
-- 	local cardsResult = {};
-- 	local result = cards:getResult();
-- 	result:collectNumber(cards, nil);
-- 	local allValues = result:getAllValueCounter():getAllValues();
-- 	-- 直接寻找对子
-- 	for _,valueTemp in ipairs(allValues)  do
-- 		if (result:getAllValueCounter():getValueCount(valueTemp) == 2) then
-- 			local partCardList = DdzTypeUtil.obtainsPartCards(cards, valueTemp, 2);
-- 			table.insert(cardsResult,DdzTypeUtil.createCloneCards(partCardList));
-- 			DdzTypeUtil.revert2Cards(cards, partCardList);
-- 		end
-- 	end
-- 	-- 拆牌（三张，炸弹）获取对子
-- 	for _,valueTemp in ipairs(allValues) do
-- 		if (result:getAllValueCounter():getValueCount(valueTemp) > 2) then
-- 			local partCardList = DdzTypeUtil.obtainsPartCards(cards, valueTemp, 2);
-- 			table.insert(cardsResult,DdzTypeUtil.createCloneCards(partCardList));
-- 			DdzTypeUtil.revert2Cards(cards, partCardList);
-- 		end
-- 	end
-- 	return cardsResult;
-- end


---
 -- 提单张牌算法，从手牌中分析出单张牌出来 <br>
 -- 比如手牌 21QJ986554443 可以出的单牌就有 5 4 2 1 Q J 9 8 6 3 考虑拆牌
 -- @DateTime 2017-11-10
 -- @param    cards [description]
 -- @param    takeJoker [description]
 -- @return    [description]
 --
M.selectSingleCards = function( cards,  takeJoker)
	-- local cardsResult = {} ;
	-- local result = cards:getResult();
	-- result:collectNumber(cards, nil);
	-- local allValues = result:getAllValueCounter():getAllValues();
	-- --// 直接寻找单张
	-- for _,valueTemp in ipairs(allValues) do
	-- 	if (result:getAllValueCounter():getValueCount(valueTemp) == 1) then
	-- 		if ((valueTemp == PokerGameConstant.RED_JOKER_SHAPE_VALUE)
	-- 				or (valueTemp == PokerGameConstant.BLACK_JOKER_SHAPE_VALUE)) then
	-- 			if (takeJoker) then
	-- 				local partCardList = DdzTypeUtil.obtainsPartCards(cards, valueTemp, 1);
	-- 				table.insert(cardsResult,DdzTypeUtil.createCloneCards(partCardList));
	-- 				M.revert2Cards(cards, partCardList);
	-- 			end
	-- 		else 
	-- 			local partCardList = DdzTypeUtil.obtainsPartCards(cards, valueTemp, 1);
	-- 			table.insert(cardsResult,DdzTypeUtil.createCloneCards(partCardList));
	-- 			M.revert2Cards(cards, partCardList);
	-- 		end
	-- 	end
	-- end
	-- --// 拆牌（三张，炸弹）获取单张
	-- for _,valueTemp in ipairs(allValues) do
	-- 	if (result:getAllValueCounter():getValueCount(valueTemp) > 1) then
	-- 		local partCardList = DdzTypeUtil.obtainsPartCards(cards, valueTemp, 1);
	-- 		table.insert(cardsResult,DdzTypeUtil.createCloneCards(partCardList));
	-- 		M.revert2Cards(cards, partCardList);
	-- 	end
	-- end
	-- return cardsResult;
	local cardsResult = M.selectTupleCountCards(cards, 1);
	if (not takeJoker) then -- // 不允许带王
		for i = #cardsResult,1,-1 do
			local cardsTemp = cardsResult[i]
			if (cardsTemp:get(1) == PokerGameConstant.RED_JOKER_SHAPE_VALUE
					or cardsTemp:get(1) == PokerGameConstant.BLACK_JOKER_SHAPE_VALUE) then
				table.remove(cardsResult,i);
			end
		end
	end
	return cardsResult;
end



--------------------------新增工具方法 提牌--------------------------------


--[[
 -- 创建Cards对象，引用的牌为深克隆
 -- @DateTime 2017-11-13
 -- @param    cardList [description]
 -- @return    [description]
 ]]
M.createCardsCopy = function(cardList)
	return M.cloneCardsAndAddCardList(nil,cardList);
end

--从指定牌列中获取部分牌，原牌不变
--从1开始
M.cloneSublistedCards = function(cards,fromIndex,toIndex)
	local cardsResult = {};
	----print("fromIndex->",fromIndex);
	----print("toIndex->",toIndex);
	----dump(cards," M.cloneSublistedCards cards");
	local cardList = cards:subList(fromIndex, toIndex);
	----dump(cardList,"M.cloneSublistedCards");
	for _,cardTemp in ipairs(cardList) do
		table.insert(cardsResult,cardTemp:clone());
	end
	return cardsResult;
end

M.cloneCardsAndAddCardList = function(cards,cardList)
	local copy = nil ;
	if not cards then
		copy = pokercore.new(Cards);
	else
		copy = cards:clone();
	end
	if cardList then
		for _,card in ipairs(cardList) do
			copy:addCard(card:clone()) ;
		end
	end 
	return copy ;
end

--[[
/**
 * 复制（深克隆）一副牌，去掉部分牌
 * 
 * @param cardList
 * @param removeCards
 * @return
 */
 ]]
M.cloneCardsAndRemoveCards  = function( cards, removeCards) 
	local copy = nil ;
	if not cards then
		copy = pokercore.new(Cards);
	else
		copy = cards:clone();
	end
	local cpCardList = copy:getCardList();
	if removeCards then
		for _,card in ipairs(removeCards:getCardList()) do
			for i = #cpCardList,1,-1 do
				local tempCard = cpCardList[i] ;
				----print("card->",card);
				----print("tempCard->",tempCard);
				 if tempCard:equals(card) then
				 	table.remove(cpCardList,i);
				 	break ;
				 end
			end
		end
	end 
	return copy ;
end


--[[
/**
 * 复制（深克隆）一副牌，添加部分牌
 * 
 * @param cardList
 * @param addCards
 * @return
 */
]]
M.cloneCardsAndAddCards = function(cards,addCards)
	local copy = nil ;
	if not cards then
		copy = pokercore.new(Cards);
	else
		copy = cards:clone();
	end
	if addCards then
		for _,card in ipairs(addCards:getCardList()) do
			copy:addCard(card:clone()) ;
		end
	end 
	return copy;
end



--[[
 * 从指定牌列中获取部分牌，原牌中移除
	 * 
	 * @param cards
	 * @param value 指定牌value值
	 * @param count 数量
	 * @return
 ]]
M.cloneRemovedCards = function(cards,value,need)
	local removedCards = {};
	local cardList = cards:getCardList() ;
	if (need > 0) then
		for i = #cardList ,1,-1 do
			local cardTemp = cardList[i] ;
			if (cardTemp:getValue() == value) then
				table.insert(removedCards,cardTemp:clone());
				table.remove(cardList,i);
				need = need - 1 ;
				if (need == 0) then
					break;
				end
			end
		end
	end
	return removedCards;
end




--[[
 * 从指定牌列中获取部分牌，原牌不变
	 * 
	 * @param cards
	 * @param value 指定牌value值
	 * @param count 数量
	 * @return
 ]]
M.cloneObtainedCards = function(cards,value,need)
	local cardsResult = {};
		if (need > 0) then
			for _,cardTemp in ipairs(cards:getCardList()) do
				if (cardTemp:getValue() == value) then
					table.insert(cardsResult,cardTemp:clone());
					need = need -1 ;
					if (need == 0) then
						break;
					end
				end
			end
		end
	return cardsResult;
end


--[[
/**
 * 是否可以找到相应顺几张的顺子 <br>
 * 期间可以用癞子去做填补，癞子不够也不行
 * 
 * @param beginValue 开始值
 * @param tupleSize 元组牌数量
 * @param straightNeed 每顺几张，单顺，双顺，三顺
 * @param tupleNum 顺几组 34567 顺5组  334455 顺三组
 * @param cards
 * @param term
 * @param result
 * @return
 */
 ]]
M.ensureTupleStaightDesc = function(beginValue, tupleNum, straightNeed
		,  cards,  term,  result) 
	local laiziCardNum = result:getLaziCardNum();
	local allNeedLaiziCardNum = 0;
	for valueTemp = beginValue,  beginValue - tupleNum + 1, -1 do -- // 从大到小
		if (valueTemp < PokerGameConstant.NUMBER_3_VALUE) then -- // 不能继续顺下去
			return false;
		end
		local valueTempNum = result:getNoneLaziValueCounter():getValueCount(valueTemp);
		local needLaziNum = straightNeed - valueTempNum; 
		needLaziNum = needLaziNum > 0 and needLaziNum or 0;  --// 防止出现负数
		allNeedLaiziCardNum = allNeedLaiziCardNum + needLaziNum;
		if (laiziCardNum < allNeedLaiziCardNum) then --// 癞子不够
			return false;
		end
	end
	return true;
end

--[[
/**
 * 提同值牌算法，从手牌中分析出n张同值牌出来 <br>
 * 比如手牌 21QJ986554443 可以出的单牌就有 5 4 2 1 Q J 9 8 6 3 考虑拆牌
 * 
 * @param cards
 * @param tupleCount 数量限制
 * @return
 */]]
M.selectTupleCountCards = function( cards,  tupleCount) 
	local cardsResult = {} ;
	local result = cards:getResult();
	result:collectNumber(cards, nil);
	local allValues = result:getAllValueCounter():getAllValues();
	--// 直接寻找
	for _,valueTemp in ipairs(allValues) do
		if (result:getAllValueCounter():getValueCount(valueTemp) == tupleCount) then
			local partCardList = DdzTypeUtil.cloneObtainedCards(cards, valueTemp, tupleCount);
			table.insert(cardsResult,DdzTypeUtil.createCardsCopy(partCardList));
		end
	end
	--// 拆牌（三张，炸弹）获取
	for _,valueTemp in ipairs(allValues) do
		if (result:getAllValueCounter():getValueCount(valueTemp) > tupleCount) then
			local partCardList = DdzTypeUtil.cloneObtainedCards(cards, valueTemp, tupleCount);
			table.insert(cardsResult,DdzTypeUtil.createCardsCopy(partCardList));
		end
	end
	return cardsResult;
end




return M ;